﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Core.Module.Interfaces.Controller;
using Core.Module.Interfaces;
using Microsoft.Practices.Unity;
using Core.Module.Interfaces.Common;
using Core.Module.Common;
using Core.Module.Interfaces.Model;
using Core.Module.Model;
using Core.Module.Interfaces.Manager;
using Core.Module.Manager;
using Core.Module.Controller;
using System.Xml.Serialization;
using System.IO;
using umbraco.BusinessLogic;
using System.Web.Script.Serialization;
using System.Xml;

namespace Core.Module
{
    public static class Context
    {
        public static IContext<IFrontend> Frontend
        {
            get
            {
                return ObjectManager.Resolve<IContext<IFrontend>>();
            }
        }

        public static IContext<IBackOffice> BackOffice
        {
            get
            {
                return ObjectManager.Resolve<IContext<IBackOffice>>();
            }
        }


        public static T FromXml<T>(this string xml)
        {
            if (string.IsNullOrEmpty(xml)) return default(T);
            XmlSerializer xs = new XmlSerializer(typeof(T));
            StringReader sr = new StringReader(xml);
            T result = default(T);
            try
            {
                result = (T)xs.Deserialize(sr);//get data from object
            }
            catch (Exception ex)
            {
                Log.Add(LogTypes.Error, -1, "Core.Modules.Context.Data.From.Xml:" + ex.Message);
            }
            return result;
        }

        public static T FromJson<T>(this string json)
        {
            if (string.IsNullOrEmpty(json)) return default(T);
            JavaScriptSerializer js = new JavaScriptSerializer();
            T result = default(T);
            try
            {
                js.RegisterConverters(ObjectManager.ResolveAll<JavaScriptConverter>());
                result = js.Deserialize<T>(json);
            }
            catch (Exception ex)
            {
                Log.Add(LogTypes.Error, -1, "Core.Modules.Context.Data.From.Json:" + ex.Message);
            }
            return result;
        }

        public static string ToXml<T>(this T data)
        {
            if (data == null) return string.Empty;
            Type t=typeof(T);
            t=t.IsInterface?data.GetType():t;
            XmlSerializer serializer = new XmlSerializer(t,"");
            XmlWriterSettings xwSettings = new XmlWriterSettings();
            xwSettings.OmitXmlDeclaration = true;
            xwSettings.Indent = false;
            
            XmlSerializerNamespaces ns=new XmlSerializerNamespaces();
            ns.Add("", "");
            using (MemoryStream stream = new MemoryStream())
            {
                XmlWriter xmlWriter = XmlWriter.Create((Stream)stream, xwSettings);
                try
                {
                    serializer.Serialize(xmlWriter, data,ns);
                }
                catch (Exception ex)
                {
                    Log.Add(LogTypes.Error, -1, "Core.Modules.Context.Data.To.Xml:" + ex.Message);
                }
                xmlWriter.Close();
                stream.Position = 0L;
                StreamReader reader = new StreamReader(stream);
                return reader.ReadToEnd();
            }
        }

        public static string ToJson<T>(this T data)
        {
            if (data == null) return string.Empty;
            JavaScriptSerializer js = new JavaScriptSerializer();
            
            StringBuilder sb = new StringBuilder();
            try
            {
                js.RegisterConverters(ObjectManager.ResolveAll<JavaScriptConverter>());
                js.Serialize(data, sb);
            }
            catch (Exception ex)
            {
                Log.Add(LogTypes.Error, -1, "Data.To.Json:" + ex.Message);
            }
            return sb.ToString();
        }
    }


    public class ContextTypeRegistrator : ITypeRegistrator
    {
        public const string lifeTypeName = "frontend";
        public IUnityContainer RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<IModuleNode, ModuleNode>();
            container.RegisterType<ISite, Site>();

            container.RegisterType<IModuleManager<IFrontend>, ModuleManager>();
            container.RegisterType<INodeManager<IFrontend>, NodeManager>(new ContainerControlledLifetimeManager());
            container.RegisterType<ISiteManager<IFrontend>, SiteManager>(new ContainerControlledLifetimeManager());

            container.RegisterType<IModuleController<IFrontend>, ModuleController>(new ContainerControlledLifetimeManager());
            container.RegisterType<INodeController<IFrontend>, NodeController>(new ContainerControlledLifetimeManager());
            container.RegisterType<ISiteController<IFrontend>, SiteController>(new ContainerControlledLifetimeManager());

            container.RegisterType<IContext<IFrontend>, DataContext<IFrontend>>(new ContainerControlledLifetimeManager());

            return container;
        }
    }

    public class ContextBackOfficeTypeRegistrator : ITypeRegistrator
    {
        public const string lifeTypeName = "backoffice";
        public IUnityContainer RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<INodeManager<IBackOffice>, NodeManagerBackOffice>(new ContainerControlledLifetimeManager());
            container.RegisterType<INodeController<IBackOffice>, NodeControllerBackOffice>(new ContainerControlledLifetimeManager());

            container.RegisterType<IContext<IBackOffice>, DataContext<IBackOffice>>(new ContainerControlledLifetimeManager());

            container.RegisterType<IApplication, ModulesApplication>("modules", new ContainerControlledLifetimeManager());
            container.RegisterInstance<IApplicationTree>("logtree",new LogManager(), new ContainerControlledLifetimeManager());
            

            return container;
        }
    }
}
